package orchestration.android;

import orchestration.persistence.OrchestratorAuthority.AndroidProcess;
import orchestration.persistence.sqlite.OrchestratorDatabaseHelper;
import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
/**
 * {@link Activity} that loads processes. User can specify a name for the process
 * and a Path to a .bpmn file, or look for it using an Open Intent File Manager Activity
 * @author <a href="mailto:car.ferrarini@gmail.com">Carlo Ferrarini</a>
 *
 */
public class LoadProcessActivity extends Activity {

	// The different distinct states the activity can be run in.
	private static final int STATE_EDIT = 0;
	private static final int STATE_INSERT = 1;

	private static final String ORIGINAL_NAME = "origName";
	private static final String ORIGINAL_PATH = "origPath";

	 // Identifiers for our menu items.
    private static final int REVERT_ID = Menu.FIRST;
    private static final int DISCARD_ID = Menu.FIRST + 1;
    private static final int DELETE_ID = Menu.FIRST + 2;

	private int mState;
	private Uri mUri;
	private Cursor mCursor;
	private EditText mPath;
	private EditText mName;
	private String mRetrievedPath;
	private String mOriginalName;
	private String mOriginalPath;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		final Intent intent = getIntent();

		// Do some setup based on the action being performed.

		final String action = intent.getAction();
		if (Intent.ACTION_EDIT.equals(action)) {
			// Requested to edit: set that state, and the data being edited.
			mState = STATE_EDIT;
			mUri = intent.getData();
		} else if (Intent.ACTION_INSERT.equals(action)) {
			// Requested to insert: set that state, and create a new entry
			// in the container.
			mState = STATE_INSERT;
			mUri = getContentResolver().insert(intent.getData(), null);

			// If we were unable to create a new process, then just finish
			// this activity.  A RESULT_CANCELED will be sent back to the
			// original activity if they requested a result.
			if (mUri == null) {
				finish();
				return;
			}

			// The new entry was created, so assume all will end well and
			// set the result to be returned.
			setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));

		} else {
			// Whoops, unknown action!  Bail.
			finish();
			return;
		}

		// Set the layout for this activity.
		setContentView(R.layout.process_loader);

		// The text view for our process's name, identified by its ID in the XML file.
		mName = (EditText) findViewById(R.id.process_name);

		// The text view for our process's path, identified by its ID in the XML file.
		mPath = (EditText) findViewById(R.id.process_path);
		Button chooseFileButton= (Button)findViewById(R.id.choose_file_button);
		chooseFileButton.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				mRetrievedPath=null;
				Intent pickFile= new Intent("org.openintents.action.PICK_FILE");
				startActivityForResult(pickFile, 1);
			}
		});
		// Get the process!
		mCursor = managedQuery(mUri, OrchestratorDatabaseHelper.PROCESS_FIELDS, null, null, null);

		// If an instance of this activity had previously stopped, we can
		// get the original text it started with.
		if (savedInstanceState != null) {
			mOriginalName = savedInstanceState.getString(ORIGINAL_NAME);
			mOriginalPath = savedInstanceState.getString(ORIGINAL_PATH);
		}

	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(data!=null)
			mRetrievedPath=data.getDataString();
	}
	  @Override
	    protected void onResume() {
	        super.onResume();

	        // If we didn't have any trouble retrieving the data, it is now
	        // time to get at the stuff.
	        if (mCursor != null) {
	            // Make sure we are at the one and only row in the cursor.
	            mCursor.moveToFirst();

	            // Modify our overall title depending on the mode we are running in.
	            if (mState == STATE_EDIT) {
	                setTitle(getText(R.string.title_edit_process));
	            } else if (mState == STATE_INSERT) {
	                setTitle(getText(R.string.title_create_process));
	            }

	            String name = mCursor.getString(mCursor.getColumnIndex(AndroidProcess.NAME));
	            mName.setText(name);
	            if(mRetrievedPath==null)
	            	mRetrievedPath = mCursor.getString(mCursor.getColumnIndex(AndroidProcess.PATH));
	            mPath.setText(mRetrievedPath);
	            
	            // If we hadn't previously retrieved the original text, do so
	            // now.  This allows the user to revert their changes.
	            if (mOriginalName == null) {
	                mOriginalName = name;
	            }
	            if (mOriginalPath == null) {
	                mOriginalPath = mRetrievedPath;
	            }

	        } else {
	            setTitle(getText(R.string.error_title));
	        }
	    }
	  
	  @Override
	    protected void onSaveInstanceState(Bundle outState) {
	        // Save away the original name and path, so we still have it if the activity
	        // needs to be killed while paused.
	        outState.putString(ORIGINAL_NAME, mOriginalName);
	        outState.putString(ORIGINAL_PATH, mOriginalPath);
	    }
	  
	  @Override
	    protected void onPause() {
	        super.onPause();

	        // The user is going somewhere else, so make sure their current
	        // changes are safely saved away in the provider.
	            String name = mName.getText().toString();
	            String path = mPath.getText().toString();
	 
	            // If this activity is finished, and there is no text, then we
	            // do something a little special: simply delete the note entry.
	            // Note that we do this both for editing and inserting...  it
	            // would be reasonable to only do it when inserting.
	            if (isFinishing() && (name.length() == 0)) {
	                setResult(RESULT_CANCELED);
	                deleteProcess();

	            // Get out updates into the provider.
	            } else {
	                ContentValues values = new ContentValues();

	                //add the name of the process and path to the xml file
	                values.put(AndroidProcess.NAME, name);
	                values.put(AndroidProcess.PATH, path);

	                // Commit all of our changes to persistent storage. When the update completes
	                // the content provider will notify the cursor of the change, which will
	                // cause the UI to be updated.
	                getContentResolver().update(mUri, values, null, null);
	            }
	    }
	  
	  @Override
	    public boolean onCreateOptionsMenu(Menu menu) {
	        super.onCreateOptionsMenu(menu);

	        // Build the menus that are shown when editing.
	        if (mState == STATE_EDIT) {
	            menu.add(0, REVERT_ID, 0, R.string.menu_revert_process)
	                    .setShortcut('0', 'r')
	                    .setIcon(android.R.drawable.ic_menu_revert);
	         
	            menu.add(0, DELETE_ID, 0, R.string.menu_delete_process)
	                    .setShortcut('1', 'd')
	                    .setIcon(android.R.drawable.ic_menu_delete);

	        // Build the menus that are shown when inserting.
	        } else {
	            menu.add(0, DISCARD_ID, 0, R.string.menu_discard_process)
	                    .setShortcut('0', 'd')
	                    .setIcon(android.R.drawable.ic_menu_delete);
	        }

	        // if we are editing a previously created process, append to the
	        // menu items for any other activities that can do stuff with it
	        // as well.  This does a query on the system for any activities that
	        // implement the ALTERNATIVE_ACTION for our data, adding a menu item
	        // for each one that is found.
	        if (mState == STATE_EDIT) {
	            Intent intent = new Intent(null, getIntent().getData());
	            intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
	            menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
	                    new ComponentName(this, LoadProcessActivity.class), null, intent, 0, null);
	        }

	        return true;
	    }

	    @Override
	    public boolean onOptionsItemSelected(MenuItem item) {
	        // Handle all of the possible menu actions.
	        switch (item.getItemId()) {
	        case DELETE_ID:
	            deleteProcess();
	            finish();
	            break;
	        case DISCARD_ID:
	        case REVERT_ID:
	            cancelProcess();
	            break;
	        }
	        return super.onOptionsItemSelected(item);
	    }

	    /**
	     * Take care of canceling work on a process.  Deletes the process if we
	     * had created it, otherwise reverts to the original text.
	     */
	    private final void cancelProcess() {
	        if (mCursor != null) {
	            if (mState == STATE_EDIT) {
	                // Put the original note text back into the database
	                mCursor.close();
	                mCursor = null;
	                ContentValues values = new ContentValues();
	                values.put(AndroidProcess.NAME, mOriginalName);
	                values.put(AndroidProcess.PATH, mOriginalPath);
	                getContentResolver().update(mUri, values, null, null);
	            } else if (mState == STATE_INSERT) {
	                // We inserted an empty note, make sure to delete it
	                deleteProcess();
	            }
	        }
	        setResult(RESULT_CANCELED);
	        finish();
	    }

	    /**
	     * Take care of deleting a note.  Simply deletes the entry.
	     */
	    private final void deleteProcess() {
	        if (mCursor != null) {
	            mCursor.close();
	            mCursor = null;
	            getContentResolver().delete(mUri, null, null);
	            mName.setText("");
	            mPath.setText("");
	        }
	    }
}
